unit telapontos;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls, BaseUnix;

type

  { TForm1 }

  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormKeyPress(Sender: TObject; var Key: char);
    procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer
      );
    procedure Timer1Timer(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end; 
  
const

  NLinhas=5;
  NColunas=5;
  resX=2048;
  resY=2048;
  DiaCir=10;
  

type
     TMathPoint = class(TObject)
     public
        x, y: extended;
        function CalculateDistanceXY(p: TMathPoint):Double;
        procedure Cruz(canvas: TCanvas; s: integer);
        procedure Ellipse(canvas: TCanvas; s: integer);
        procedure Pixels(canvas: TCanvas; cor: TColor);
        procedure Line(canvas: TCanvas; p: TMathPoint);
        destructor Destroy; override;
     end;

  devicetoken=string[6];
  posicao=record
         xy: TMathPoint;
         uv: TMathPoint;
         gravado: boolean;
         end;
  vertex=record
       distance: Extended;
       xy: TMathPoint;
       index: integer;
       end;
  xy=record
          x,y: integer;
          end;

  xyd=record
          x,y,d: extended;
      end;
          

     TImageCal= class(TImage)
     public
        // Estrutura nova
        point_xy: array[0..100] of TMathPoint;
        points_xy: integer;
        point_uv: array[0..100] of TMathPoint;
        points_uv: integer;
        gravado: array[0..100] of boolean;
        distuv: array[0..100] of extended;
        distxy: array[0..100] of extended;
        vertice: array[0..4] of vertex; // Triangulo


        // Estrutura antiga
        ix,iy: integer;
        xCursor, yCursor: integer;
        DebugPipe: integer;
        modo: shortint;
        procedure Converte_UV_XY_Contravariante(var pos: posicao);
        procedure Converte_UV_XY_Beto(var pos: posicao);
        procedure Converte_UV_XY(var pos: posicao);
        procedure Converte_XY_UV(var Pos: posicao);  // descobre qual eh o UV relacionado a um XY
        function ProcessaCoordenada(p: TMathPoint):TMathPoint;
//        procedure ProcessaCoordenadaUV(p: TMathPoint);
        procedure Grava;
        procedure Load;
        procedure GravaMatriz;
        procedure GravaMatrizCalibracao;
//        procedure SalvaXY;
//        procedure Reset;
        procedure MostraTriangulo;
        Procedure Proximo;
        procedure MostraMatrizToques;
        procedure MostraPontoToque(p: TMathPoint);
        procedure Pinta;
        constructor Create(Aowner: TComponent); override;
        procedure MouseMove(Shift: TShiftState; x,y: integer); override;
     end;

     TTriangle = class(TObject)
     public
        vortex: array[0..2] of TMathPoint;
     private

     end;

//     TPlane = class(TObject)
//     public
//        points
//     private
//
//     end;

var
  Form1: TForm1; 
  ImageCal: TImageCal;
  ratiox,ratioy: Double; // Aspecto XY
  te: textfile;
  te2: file of byte;
  ContaArquivos: integer;

implementation

{ TForm1 }


destructor TMathPoint.Destroy;

begin

  inherited Destroy;

end;


function Orientation(const x1, y1, x2, y2, Px, Py: Double): Integer;
var
  Orin: Double;
begin
  (* Linear determinant of the 3 points *)
  Orin := (x2 - x1) * (py - y1) - (px - x1) * (y2 - y1);

  if Orin > 0.0 then
    Result := +1             (* Orientaion is to the right-hand side *)
  else if Orin < 0.0 then
    Result := -1             (* Orientaion is to the left-hand side  *)
  else
    Result := 0;             (* Orientaion is neutral aka collinear  *)
end;
(* End of Orientation *)

function PointInTriangle(const Px, Py, x1, y1, x2, y2, x3, y3: Double): Boolean;
var
  Or1: Integer;
  Or2: Integer;
  Or3: Integer;
begin
  Or1 := Orientation(x1, y1, x2, y2, Px, Py);
  Or2 := Orientation(x2, y2, x3, y3, Px, Py);
  Or3 := Orientation(x3, y3, x1, y1, Px, Py);

  if (Or1 = Or2) and (Or2 = Or3) then
    Result := True
  else if Or1 = 0 then
    Result := (Or2 = 0) or (Or3 = 0)
  else if Or2 = 0 then
    Result := (Or1 = 0) or (Or3 = 0)
  else if Or3 = 0 then
    Result := (Or2 = 0) or (Or1 = 0)
  else
    Result := False;
end;
(* End of PointInTriangle *)


function oProprio(i: integer): integer;

begin

result:=i

end;


function depois(i: integer): integer;

begin
  if i<3 then result:=i+1 else result:=0;

end;

function antes(i: integer): integer;

begin
   if i>0 then result:=i-1 else result:=3;
end;


{function BilinearParcel(xi,uj,ux,xj,ui:double):double;
begin
//if (uj-ui)=0 then Result:=1e10 else
Result:=(xi*(uj-ux)+xj*(ux-ui))/(uj-ui);
end;

function Vinterpol(vi,ui,vj,uj:double; var pos: posicao):double;
begin
//if (uj-ui)=0 then Result:=1e10 else
Result:=vi+((pos.uv.x-ui)*(vj-vi))/(uj-ui);
end;

procedure TImageCal.Converte_UV_XY_Beto(var pos: posicao);

var xp0,xp1,vp0,vp1,yp0,yp1: double;

begin

// point_uv[vertice[i].index].x; vertice[0..3] point_uv[0..100]

writeln(te,'uv-vertice-0 -> ('+floattostr(point_uv[vertice[oProprio(0)].index].x)+','+floattostr(point_uv[vertice[oProprio(0)].index].y));
writeln(te,'uv-vertice-1 -> ('+floattostr(point_uv[vertice[oProprio(1)].index].x)+','+floattostr(point_uv[vertice[oProprio(1)].index].y));
writeln(te,'uv-vertice-2 -> ('+floattostr(point_uv[vertice[oProprio(2)].index].x)+','+floattostr(point_uv[vertice[oProprio(2)].index].y));
writeln(te,'uv-vertice-3 -> ('+floattostr(point_uv[vertice[oProprio(3)].index].x)+','+floattostr(point_uv[vertice[oProprio(3)].index].y));
writeln(te,'*************************************************');
writeln(te,'xy-vertice-0 -> ('+floattostr(point_xy[vertice[oProprio(0)].index].x)+','+floattostr(point_xy[vertice[oProprio(0)].index].y));
writeln(te,'xy-vertice-1 -> ('+floattostr(point_xy[vertice[oProprio(1)].index].x)+','+floattostr(point_xy[vertice[oProprio(1)].index].y));
writeln(te,'xy-vertice-2 -> ('+floattostr(point_xy[vertice[oProprio(2)].index].x)+','+floattostr(point_xy[vertice[oProprio(2)].index].y));
writeln(te,'xy-vertice-3 -> ('+floattostr(point_xy[vertice[oProprio(3)].index].x)+','+floattostr(point_xy[vertice[oProprio(3)].index].y));
writeln(te,'------------------------------------------------------------------');
writeln(te);


xp0:=BilinearParcel
      (point_xy[vertice[oProprio(0)].index].x,point_uv[vertice[oProprio(1)].index].x,pos.uv.x,point_xy[vertice[oProprio(1)].index].x,point_uv[vertice[oProprio(0)].index].x);
xp1:=BilinearParcel
      (point_xy[vertice[oProprio(2)].index].x,point_uv[vertice[oProprio(3)].index].x,pos.uv.x,point_xy[vertice[oProprio(3)].index].x,point_uv[vertice[oProprio(0)].index].x);
vp0:=Vinterpol
      (point_uv[vertice[oProprio(0)].index].y,point_uv[vertice[oProprio(0)].index].x,point_uv[vertice[oProprio(1)].index].y,point_uv[vertice[oProprio(1)].index].x,pos);
vp1:=Vinterpol
      (point_uv[vertice[oProprio(2)].index].y,point_uv[vertice[oProprio(2)].index].x,point_uv[vertice[oProprio(3)].index].y,point_uv[vertice[oProprio(3)].index].x,pos);
pos.xy.x:= BilinearParcel(xp0,vp1,pos.uv.y,xp1,vp0);

yp0:=BilinearParcel(point_xy[vertice[oProprio(0)].index].y,point_uv[vertice[oProprio(1)].index].x,pos.uv.x,point_xy[vertice[oProprio(1)].index].y,point_uv[vertice[oProprio(0)].index].x);
yp1:=BilinearParcel(point_xy[vertice[oProprio(2)].index].y,point_uv[vertice[oProprio(3)].index].x,pos.uv.x,point_xy[vertice[oProprio(3)].index].y,point_uv[vertice[oProprio(0)].index].x);
pos.xy.y:= BilinearParcel(yp0,vp1,pos.uv.y,yp1,vp0);

end;}

function BilinearParcel(xi,uj,ux,xj,ui:double):double;
begin
     Result:=(xi*(uj-ux)+xj*(ux-ui))/(uj-ui);
end;

function Vinterpol(vi,ui,vj,uj:double; var pos: posicao):double;
begin
     Result:=vi+((pos.uv.x-ui)*(vj-vi))/(uj-ui);
end;

procedure TImageCal.Converte_UV_XY_Beto(var pos: posicao);

var xp0,xp1,vp0,vp1,yp0,yp1: double;

begin

// point_uv[vertice[i].index].x; vertice[0..3]   point_uv[0..100]

xp0:=BilinearParcel(point_xy[vertice[0].index].x,point_uv[vertice[3].index].x,pos.uv.x,point_xy[vertice[3].index].x,point_uv[vertice[0].index].x);
xp1:=BilinearParcel(point_xy[vertice[1].index].x,point_uv[vertice[2].index].x,pos.uv.x,point_xy[vertice[2].index].x,point_uv[vertice[1].index].x);
vp0:=Vinterpol(point_uv[vertice[0].index].y,point_uv[vertice[0].index].x,point_uv[vertice[3].index].y,point_uv[vertice[3].index].x,pos);
vp1:=Vinterpol(point_uv[vertice[1].index].y,point_uv[vertice[1].index].x,point_uv[vertice[2].index].y,point_uv[vertice[2].index].x,pos);
pos.xy.x:= BilinearParcel(xp0,vp1,pos.uv.y,xp1,vp0);

yp0:=BilinearParcel(point_xy[vertice[0].index].y,point_uv[vertice[3].index].x,pos.uv.x,point_xy[vertice[3].index].y,point_uv[vertice[0].index].x);
yp1:=BilinearParcel(point_xy[vertice[1].index].y,point_uv[vertice[2].index].x,pos.uv.x,point_xy[vertice[2].index].y,point_uv[vertice[1].index].x);
pos.xy.y:= BilinearParcel(yp0,vp1,pos.uv.y,yp1,vp0);

end;




procedure TImageCal.Converte_UV_XY_Contravariante(var pos: posicao);

var vetor1,vetor2: TMathPoint; // apesar de ser tipo posicaotriangulo, os vetores1 e 2 sao na verdade os vetores de dois lados nao necessariamente ortogonais do triangulo
    base1, base2, vetorXY: TMathPoint; // a mesma coisa que acima
     d1, d2, d3, p1, p2,p1l,p2l: extended; // dn eh o tamanho do vetor base n  e pn eh a projecao do vetorXY na base n
     pvertical,phorizontal: extended; // proporcoes em relacao aos eixos nao necessariamente ortogonais
     i: integer;
     CT, v0,v1,v2: integer; // esta variavel vai percorrer os 4 triangulos que circundam um ponto
     Guarda4Vertices: array[0..3] of xyd;
     PontoDeMostrar:TMathPoint;
     mediaX, mediaY, denom: extended; //denom eh a soma de todos os pesos que na verdade sao o inverso da distancia ao ponto de calculo
     cosalfa: extended;
     senalfa2: extended;
     flag: boolean;


begin
//note que vertice tras uma organizacao semelhante a Converte_XY_UV onde nao exite angulo ortogonal porque em UV nao eh necessariamente ortogonal
//note que esta versao da funcao usa coordenadas projetadas atraves de paralelogramas, ou seja, coordenadas contravariantes



base1:=TMathPoint.create;
base2:=TMathPoint.create;
vetorXY:=TMathPoint.create;
vetor1:=TMathPoint.create;
vetor2:=TMathPoint.create;


for CT:=0 to 3 do

begin


// showmessage('1');

base1.x:=point_uv[vertice[depois(CT)].index].x-point_uv[vertice[CT].index].x;//coordenada x do vetor de base1 tomada em relacao ao vertice de origem
base1.y:=point_uv[vertice[depois(CT)].index].y-point_uv[vertice[CT].index].y;// coordenada y do vetor de base1 tomada em relacao ao vertice de origem

// showmessage('2');

base2.x:=point_uv[vertice[antes(CT)].index].x-point_uv[vertice[CT].index].x;//coordenada x do vetor de base2 tomada em relacao ao vertice de origem
base2.y:=point_uv[vertice[antes(CT)].index].y-point_uv[vertice[CT].index].y;//coordenada y do vetor de base2 tomada em relacao ao vertice de origem

// showmessage('3');
vetorXY.x:=pos.uv.x-point_uv[vertice[CT].index].x;//coordenada x do vetor que vai mudar de espaco em relacao a origem
vetorXY.y:=pos.uv.y-point_uv[vertice[CT].index].y;//coordenada x do vetor que vai mudar de espaco em relacao a origem

// showmessage('4');
d1:=sqrt(base1.x*base1.x+base1.y*base1.y);// tamanho da base 1
d2:=sqrt(base2.x*base2.x+base2.y*base2.y);// tamanho da base 2

// showmessage('5');
if d1=0 then p1:=0 else p1:=(vetorXY.x*base1.x+vetorXY.y*base1.y)/d1; // encontra projecao usando produto interno
if d2=0 then p2:=0 else p2:=(vetorXY.x*base2.x+vetorXY.y*base2.y)/d2;
// showmessage('6');

flag:=false;



if (d1<>0) and (d2<>0) then cosalfa:=(base1.x*base2.x+base1.y*base2.y)/(d1*d2) else ShowMessage('Divisao por zero: um dos vetores da base eh nulo!');

senalfa2:=1-cosalfa*cosalfa;

p1l:=(1/senalfa2)*(p1-p2*cosalfa);
p2l:=(1/senalfa2)*(p2-p1*cosalfa);

{if (p1l<0) or (p2l<0) then

begin

flag:=true;

writeln(te,'u,v: '+floattostr(pos.uv.x)+','+floattostr(pos.uv.y));
       writeln(te,'vertice-index: '+inttostr(vertice[CT].index)+','+inttostr(vertice[antes(CT)].index)+','+inttostr(vertice[depois(CT)].index));
writeln(te,'vertice-pos: '+floattostr(point_uv[vertice[CT].index].x)+','+floattostr(point_uv[vertice[antes(CT)].index].x)+','+floattostr(point_uv[vertice[depois(CT)].index].x));
writeln(te,'produto interno p1: '+floattostr(vetorXY.x*base1.x+vetorXY.y*base1.y)+','+floattostr(vetorXY.x*base2.x+vetorXY.y*base2.y));
writeln(te,'d1,d2: '+floattostr(d1)+','+floattostr(d2));
writeln(te,'p1,p2: '+floattostr(p1)+','+floattostr(p2));


writeln(te,'Contravariante-p1,p2: '+floattostr(p1l)+','+floattostr(p2l));
writeln(te,'*****');

end;}

p1:=p1l;
p2:=p2l;

if d1=0 then pvertical:=0 else pvertical:=p1/(d1);   // proporcao na vertical
if d2=0 then phorizontal:=0 else phorizontal:=p2/(d2); // proporcao na horizontal
// showmessage('7');
vetor1.x:=point_xy[vertice[depois(CT)].index].x-point_xy[vertice[CT].index].x;
vetor1.y:=point_xy[vertice[depois(CT)].index].y-point_xy[vertice[CT].index].y;
// showmessage('8');
vetor2.x:=point_xy[vertice[antes(CT)].index].x-point_xy[vertice[CT].index].x;
vetor2.y:=point_xy[vertice[antes(CT)].index].y-point_xy[vertice[CT].index].y;
// showmessage('9');
vetor1.x:=vetor1.x*pvertical;
vetor1.y:=vetor1.y*pvertical;
// showmessage('10');
vetor2.x:=vetor2.x*phorizontal;
vetor2.y:=vetor2.y*phorizontal;
// showmessage('11');


Guarda4Vertices[CT].x:=vetor1.x+vetor2.x+point_xy[vertice[CT].index].x;
Guarda4Vertices[CT].y:=vetor1.y+vetor2.y+point_xy[vertice[CT].index].y;

{if ((PointInTriangle(Guarda4Vertices[CT].x, Guarda4Vertices[CT].y,
                    point_xy[vertice[0].index].x,point_xy[vertice[0].index].y,
                    point_xy[vertice[1].index].x,point_xy[vertice[1].index].y,
                    point_xy[vertice[2].index].x,point_xy[vertice[2].index].y
                    )
   )
   or
   (PointInTriangle(Guarda4Vertices[CT].x, Guarda4Vertices[CT].y,
                    point_xy[vertice[2].index].x,point_xy[vertice[2].index].y,
                    point_xy[vertice[3].index].x,point_xy[vertice[3].index].y,
                    point_xy[vertice[0].index].x,point_xy[vertice[0].index].y)
                     ) )}
                     
                     
if ((phorizontal<=1)and(pvertical<=1))
                    then
                    Guarda4Vertices[CT].d:=abs(vertice[CT].distance*vertice[CT].distance*vertice[CT].distance*
                           vertice[CT].distance*vertice[CT].distance*vertice[CT].distance*
                           vertice[CT].distance*vertice[CT].distance*vertice[CT].distance*
                           vertice[CT].distance*vertice[CT].distance)
                     else
                       begin
                             PontoDeMostrar:=TMathPoint.Create;
                             POntoDeMostrar.x:=Guarda4Vertices[CT].x;
                             POntoDeMostrar.y:=Guarda4Vertices[CT].y;
                             PontoDeMostrar.Ellipse(canvas,1);
                             PontoDeMostrar.Destroy;

                          Guarda4Vertices[CT].x:=-1e20;
                          Guarda4Vertices[CT].y:=-1e20;
                       end;








end; {for ContaTriangulos}

base1.destroy;
base2.destroy;
vetorXY.destroy;
vetor1.destroy;
vetor2.destroy;


mediaX:=0;
mediaY:=0;
denom:=0;

for CT:=0 to 3 do
   begin
       if Guarda4Vertices[CT].d=0 then
          begin
             mediaX:=Guarda4Vertices[CT].x;
             mediaY:=Guarda4Vertices[CT].y;
             denom:=1;
             break;
          end
       else
        if (Guarda4Vertices[CT].x>-1e19) and (Guarda4Vertices[CT].x>-1e19)  then
          begin
            mediaX:=mediaX+Guarda4Vertices[CT].x*abs(1/Guarda4Vertices[CT].d);
            mediaY:=mediaY+Guarda4Vertices[CT].y*abs(1/Guarda4Vertices[CT].d);
            denom:=denom+(1/Guarda4Vertices[CT].d)
          end;
   end;


if denom=0 then
       //    writeln(te,'u,v: '+floattostr(pos.uv.x)+','+floattostr(pos.uv.y))
else
begin
     pos.xy.x:=mediaX/denom;
     pos.xy.y:=mediaY/denom;
end;


//writeln(te,'v0uv('+floattostr(point_uv[vertice[0].index].x)+','+floattostr(point_uv[vertice[0].index].y)+') '+
//                   ' v1xy('+floattostr(point_uv[vertice[1].index].x)+','+floattostr(point_uv[vertice[1].index].y)+') '+
//                   ' v2xy('+floattostr(point_uv[vertice[2].index].x)+','+floattostr(point_uv[vertice[2].index].y)+') ');
//writeln(te,'uv('+floattostr(pos.uv.x)+','+floattostr(pos.uv.y)+
//               ') d12 p12('+floattostr(d1)+','+floattostr(d2)+','+floattostr(p1)+','+floattostr(p2)+')' +
//               'phv('+floattostr(phorizontal)+','+floattostr(pvertical)+') '+
//              ' xy('+floattostr(pos.xy.x)+','+floattostr(pos.xy.y)+')');



end;




procedure TImageCal.Converte_UV_XY(var pos: posicao);

var vetor1,vetor2: TMathPoint; // apesar de ser tipo posicaotriangulo, os vetores1 e 2 sao na verdade os vetores de dois lados nao necessariamente ortogonais do triangulo
    base1, base2, vetorXY: TMathPoint; // a mesma coisa que acima
     d1, d2, p1, p2: extended; // dn eh o tamanho do vetor base n  e pn eh a projecao do vetorXY na base n
     pvertical,phorizontal: extended; // proporcoes em relacao aos eixos nao necessariamente ortogonais
     i: integer;
     CT, v0,v1,v2: integer; // esta variavel vai percorrer os 4 triangulos que circundam um ponto
     Guarda4Vertices: array[0..3] of xyd;
     mediaX, mediaY, denom: extended; //denom eh a soma de todos os pesos que na verdade sao o inverso da distancia ao ponto de calculo


begin
//note que vertice tras uma organizacao semelhante a Converte_XY_UV onde nao exite angulo ortogonal porque em UV nao eh necessariamente ortogonal
//note que esta versao da funcao usa coordenadas projetadas ortogonalmente. Seria melhor usar coordenadas contravariantes


base1:=TMathPoint.create;
base2:=TMathPoint.create;
vetorXY:=TMathPoint.create;
vetor1:=TMathPoint.create;
vetor2:=TMathPoint.create;


for CT:=0 to 3 do

begin


// showmessage('1');

base1.x:=point_uv[vertice[depois(CT)].index].x-point_uv[vertice[CT].index].x;//coordenada x do vetor de base1 tomada em relacao ao vertice de origem
base1.y:=point_uv[vertice[depois(CT)].index].y-point_uv[vertice[CT].index].y;// coordenada y do vetor de base1 tomada em relacao ao vertice de origem

// showmessage('2');

base2.x:=point_uv[vertice[antes(CT)].index].x-point_uv[vertice[CT].index].x;//coordenada x do vetor de base2 tomada em relacao ao vertice de origem
base2.y:=point_uv[vertice[antes(CT)].index].y-point_uv[vertice[CT].index].y;//coordenada y do vetor de base2 tomada em relacao ao vertice de origem

// showmessage('3');
vetorXY.x:=pos.uv.x-point_uv[vertice[CT].index].x;//coordenada x do vetor que vai mudar de espaco em relacao a origem
vetorXY.y:=pos.uv.y-point_uv[vertice[CT].index].y;//coordenada x do vetor que vai mudar de espaco em relacao a origem

// showmessage('4');
d1:=sqrt(base1.x*base1.x+base1.y*base1.y);// tamanho da base 1
d2:=sqrt(base2.x*base2.x+base2.y*base2.y);// tamanho da base 2
// showmessage('5');
if d1=0 then p1:=0 else p1:=(vetorXY.x*base1.x+vetorXY.y*base1.y)/d1; // encontra projecao usando produto interno
if d2=0 then p2:=0 else p2:=(vetorXY.x*base2.x+vetorXY.y*base2.y)/d2;
// showmessage('6');

if d1=0 then pvertical:=0 else pvertical:=p1/(d1);   // proporcao na vertical
if d2=0 then phorizontal:=0 else phorizontal:=p2/(d2); // proporcao na horizontal
// showmessage('7');
vetor1.x:=point_xy[vertice[depois(CT)].index].x-point_xy[vertice[CT].index].x;
vetor1.y:=point_xy[vertice[depois(CT)].index].y-point_xy[vertice[CT].index].y;
// showmessage('8');
vetor2.x:=point_xy[vertice[antes(CT)].index].x-point_xy[vertice[CT].index].x;
vetor2.y:=point_xy[vertice[antes(CT)].index].y-point_xy[vertice[CT].index].y;
// showmessage('9');
vetor1.x:=vetor1.x*pvertical;
vetor1.y:=vetor1.y*pvertical;
// showmessage('10');
vetor2.x:=vetor2.x*phorizontal;
vetor2.y:=vetor2.y*phorizontal;
// showmessage('11');



Guarda4Vertices[CT].x:=vetor1.x+vetor2.x+point_xy[vertice[CT].index].x;
Guarda4Vertices[CT].y:=vetor1.y+vetor2.y+point_xy[vertice[CT].index].y;
Guarda4Vertices[CT].d:=abs(vertice[CT].distance*vertice[CT].distance*vertice[CT].distance*vertice[CT].distance*vertice[CT].distance*vertice[CT].distance);


end; {for ContaTriangulos}

base1.destroy;
base2.destroy;
vetorXY.destroy;
vetor1.destroy;
vetor2.destroy;


mediaX:=0;
mediaY:=0;
denom:=0;

for CT:=0 to 3 do
   begin
       if Guarda4Vertices[CT].d=0 then
          begin
             mediaX:=Guarda4Vertices[CT].x;
             mediaY:=Guarda4Vertices[CT].y;
             denom:=1;
             break;
          end
       else
          begin
            mediaX:=mediaX+Guarda4Vertices[CT].x*abs(1/Guarda4Vertices[CT].d);
            mediaY:=mediaY+Guarda4Vertices[CT].y*abs(1/Guarda4Vertices[CT].d);
            denom:=denom+(1/Guarda4Vertices[CT].d)
          end;
   end;

pos.xy.x:=mediaX/denom;
pos.xy.y:=mediaY/denom;


//writeln(te,'v0uv('+floattostr(point_uv[vertice[0].index].x)+','+floattostr(point_uv[vertice[0].index].y)+') '+
//                   ' v1xy('+floattostr(point_uv[vertice[1].index].x)+','+floattostr(point_uv[vertice[1].index].y)+') '+
//                   ' v2xy('+floattostr(point_uv[vertice[2].index].x)+','+floattostr(point_uv[vertice[2].index].y)+') ');
//writeln(te,'uv('+floattostr(pos.uv.x)+','+floattostr(pos.uv.y)+
//               ') d12 p12('+floattostr(d1)+','+floattostr(d2)+','+floattostr(p1)+','+floattostr(p2)+')' +
//               'phv('+floattostr(phorizontal)+','+floattostr(pvertical)+') '+
//              ' xy('+floattostr(pos.xy.x)+','+floattostr(pos.xy.y)+')');



end;


procedure TImageCal.Converte_XY_UV(var pos: posicao);

var vetor1,vetor2: TMathPoint; // apesar de ser tipo posicaotriangulo, os vetores1 e 2 sao na verdade os vetores de dois lados ortogonais do triangulo
     d1, d2, d3, d4: double;
     pvertical,phorizontal: extended; // proporcoes em relacao aos eixos ortogonais
     i: integer;
begin

vetor1:=TMathPoint.create;
vetor2:=TMathPoint.create;

d1:=abs(point_xy[vertice[1].index].x-point_xy[vertice[0].index].y); // tamanho do vetor vertical
d2:=abs(point_xy[vertice[2].index].x-point_xy[vertice[0].index].x); // tamanho do vetor horizontal

d3:=abs(pos.xy.y-point_xy[vertice[0].index].y); // tamanho da projecao do ponto a ser convertido no vetor vertical
d4:=abs(pos.xy.x-point_xy[vertice[0].index].x); // tamanho da projecao do ponto a ser convertido no vetor horizontal

if d2=0 then phorizontal:=0 else phorizontal:=d4/(d2); // proporcao na horizontal
if d1=0 then pvertical:=0 else pvertical:=d3/(d1);   // proporcao na vertical

vetor1.x:=point_uv[vertice[2].index].x-point_uv[vertice[0].index].x; // vetor 1 eh o vetor no espaco uv correspondente ao vetor horizontal no espaco xy
vetor1.y:=point_uv[vertice[2].index].y-point_uv[vertice[0].index].y;

vetor2.x:=point_uv[vertice[1].index].x-point_uv[vertice[0].index].x; // vetor 1 eh o vetor no espaco uv correspondente ao vetor VERTICAL no espaco xy
vetor2.y:=point_uv[vertice[1].index].y-point_uv[vertice[0].index].y;

vetor1.x:=vetor1.x*phorizontal;
vetor1.y:=vetor1.y*phorizontal;

vetor2.y:=vetor2.y*pvertical;
vetor2.x:=vetor2.x*pvertical;

pos.uv.x:=vetor1.x+vetor2.x+point_uv[vertice[0].index].x;
pos.uv.y:=vetor1.y+vetor2.y+point_uv[vertice[0].index].y;

vetor1.destroy;
vetor2.destroy;


//if (pos.x=2) and (Form2.Memo1.Lines.Count<=300) then
//begin
//Form2.Memo1.Append('v0xy('+inttostr(vertice[0].xorig)+','+inttostr(vertice[0].yorig)+') '+
//                   ' v1xy('+inttostr(vertice[1].xorig)+','+inttostr(vertice[1].yorig)+') '+
//                   ' v2xy('+inttostr(vertice[2].xorig)+','+inttostr(vertice[2].yorig)+') ');
//Form2.Memo1.Append('xy('+inttostr(pos.x)+','+inttostr(pos.y)+
//               ') d1234('+inttostr(d1)+','+inttostr(d2)+','+inttostr(d3)+','+inttostr(d4)+')' +
//               'phv('+floattostr(phorizontal)+','+floattostr(pvertical)+') '+
//               ' uv('+inttostr(pos.u)+','+inttostr(pos.v)+')');
//Form2.Memo1.Append(' origxy('+inttostr(vertice[1].yorig)+','+inttostr(vertice[0].yorig) + ')');
//end;
//   Application.ProcessMessages;
//if Form2.Memo1.Lines.Count=100 then // showmessage('paradinha');
end;

function TMathPoint.CalculateDistanceXY(p: TMathPoint):Double;
begin
   Result:=Sqrt((p.x-x)*(p.x-x)+(p.y-y)*(p.y-y));
end;
procedure TMathPoint.Cruz(canvas: TCanvas; s: integer);
begin
  Canvas.Pen.Color:=clRed;
  Canvas.Pen.Width:=1;
  Canvas.Moveto(Trunc((x)*ratiox),Trunc((y-s)*ratioy));
  Canvas.LineTo(Trunc((x)*ratiox),Trunc((y+s)*ratioy));
  Canvas.MoveTo(Trunc((x-s)*ratiox),Trunc((y)*ratioy));
  Canvas.LineTo(Trunc((x+s)*ratiox),Trunc((y)*ratioy));
end;

procedure TMathPoint.Ellipse(canvas: TCanvas; s: integer);
begin
  Canvas.Pen.Color:=clBlack;
  Canvas.Pen.Width:=1;
  canvas.Ellipse(Trunc((x-s)*ratiox),Trunc((y-s)*ratioy),Trunc((x+s)*ratiox),Trunc((y+s)*ratioy));
end;

procedure TMathPoint.Pixels(canvas: TCanvas; cor: TColor);
begin
  canvas.Pixels[Trunc((x)*ratiox),Trunc((y)*ratioy)]:=cor;
end;


procedure TMathPoint.Line(canvas: TCanvas; p: TMathPoint);
begin
   Canvas.Pen.Color:=clBlue;
   canvas.Line(Trunc(x*ratiox),Trunc(y*ratioy),Trunc(p.x*ratiox),Trunc(p.y*ratioy));
end;

//procedure TImageCal.ProcessaCoordenadaUV(p: TMathPoint);
//var
//  i: integer;
//begin
  // Mapa de distancias
//  for i:=0 to points_uv do
//  begin
//       distxy[i].xorig:=Trunc(point_uv[i].x);
//       distxy[i].yorig:=Trunc(point_uv[i].y);
//       distxy[i].value:=p.CalculateDistance(point_uv[i]);
//  end;
// end;


function TImageCal.ProcessaCoordenada(p: TMathPoint):TMathPoint;
var
   a,b,c,d: integer;
   tmpvertice: vertex;
   pos: posicao;
begin

// Encontra Poligono de quatro lados que contem o ponto

         pos.uv:=TMathPoint.Create;
         pos.uv.x:=p.x;
         pos.uv.y:=p.y;
         pos.xy:=TMathPoint.Create;

          vertice[0].index:=-1;
          vertice[1].index:=-1;
          vertice[2].index:=-1;
          vertice[3].index:=-1;

for a:=0 to points_uv-1-NColunas do

begin

//if not( ( (a+1) div NColunas)=((a+1)/NColunas)) then
if not( ( (a+1) mod NColunas)=0) then

if (PointInTriangle(pos.uv.x, pos.uv.y,
                    point_uv[a].x,point_uv[a].y,
                    point_uv[a+1].x,point_uv[a+1].y,
                    point_uv[a+1+NColunas].x,point_uv[a+1+NColunas].y
                    )
   )
   or
   (PointInTriangle(pos.uv.x, pos.uv.y,
                    point_uv[a].x,point_uv[a].y,
                    point_uv[a+NColunas].x,point_uv[a+NColunas].y,
                    point_uv[a+1+NColunas].x,point_uv[a+1+NColunas].y
                    )
   )
   then
      begin
          vertice[0].index:=a;
          vertice[1].index:=a+1;
          vertice[2].index:=a+1+NColunas;
          vertice[3].index:=a+NColunas;
          vertice[0].xy:=point_uv[a];
          vertice[1].xy:=point_uv[a+1];
          vertice[2].xy:=point_uv[a+1+NColunas];
          vertice[3].xy:=point_uv[a+NColunas];
          vertice[0].distance:=p.CalculateDistanceXY(vertice[0].xy);
          vertice[1].distance:=p.CalculateDistanceXY(vertice[1].xy);
          vertice[2].distance:=p.CalculateDistanceXY(vertice[2].xy);
          vertice[3].distance:=p.CalculateDistanceXY(vertice[3].xy);
      end;
end;



{       // Calcula vertices mais proximos
       // showmessage('a');
       d:=0;
       
       //writeln(te,'->'+inttostr(points_uv));
       for a:=0 to points_uv -1  do
       begin

          vertice[d].index:=a;
          vertice[d].xy:=point_uv[a];
          vertice[d].distance:=p.CalculateDistanceXY(point_uv[a]);
          //writeln(te,'pxy>'+floattostr(p.x)+','+floattostr(p.y)+'   d-'+inttostr(d)+ '  index- '+inttostr(a)+'  point_uv[a]-'+floattostr(point_uv[a].x)+','+floattostr(point_uv[a].y)+ '  distance-'+floattostr(vertice[d].distance));

          // Ordena todos os itens acumulados em vertice
          for c:=0 to d-1 do
          begin
            if (vertice[c].distance>vertice[c+1].distance) then
            begin
              tmpvertice:=vertice[c];
              vertice[c]:=vertice[c+1];
              vertice[c+1]:=tmpvertice;
              //writeln(te,'c>'+inttostr(c)+' index>'+inttostr(vertice[c].index));
            end;
          end;
          if d<4 then d:=d+1;
       end;

       for c:=0 to d-2 do
         begin
           if not(((vertice[c].index=vertice[c+1].index+1) or (vertice[c].index+1=vertice[c+1].index))
           or ((vertice[c].index=vertice[c+1].index + NColunas)or ((vertice[c].index+NColunas=vertice[c+1].index))))
                then
                  begin
                     tmpvertice:=vertice[c+2];
                     vertice[c+2]:=vertice[c+1];
                     vertice[c+1]:=tmpvertice;
                  end;

         
         
         end;}

{
       d:=3;
       // showmessage('b');
         // Encontra ponto ortogonal
         for c:=1 to d-1 do
         begin
           if ((vertice[0].index=vertice[1].index+1) or (vertice[0].index+1=vertice[1].index))
           and ((vertice[0].index=vertice[2].index + NColunas)or ((vertice[0].index+NColunas=vertice[2].index))) then break;
           if ((vertice[0].index=vertice[2].index+1) or (vertice[0].index+1=vertice[2].index))
           and ((vertice[0].index=vertice[1].index + NColunas)or ((vertice[0].index+NColunas=vertice[1].index))) then break;


//           if ((vertice[0].xy.x=vertice[1].xy.x) and (vertice[0].xy.y=vertice[2].xy.y)) then break;
//           if ((vertice[0].xy.x=vertice[2].xy.x) and (vertice[0].xy.y=vertice[1].xy.y)) then break;
           tmpvertice:=vertice[0];
           vertice[0]:=vertice[c];
           vertice[c]:=tmpvertice;
         end;

         // showmessage('c');
         // Encontra cateto vertical
//         if not (vertice[0].xy.x=vertice[1].xy.x) then
//           if vertice[0].xy.x<>vertice[1].xy.x then
           if not((vertice[0].index=vertice[1].index +NColunas) or ((vertice[0].index+NColunas=vertice[1].index))) then
           begin
             tmpvertice:=vertice[1];
             vertice[1]:=vertice[2];
             vertice[2]:=tmpvertice;
           end;
}

           // showmessage('d');
         //writeln(te,'ordem de triangulos(vertice012):'+inttostr(vertice[0].index)+','+inttostr(vertice[1].index)+','+inttostr(vertice[2].index));


         //writeln(te,'vai verificar se esta dentro do quadrado');
         //flush(te);
         if
                   vertice[0].index+
                   vertice[1].index+
                   vertice[2].index+
                   vertice[3].index<0
         then
             begin
                //writeln(te,'Ponto uv('+floattostr(pos.uv.x)+','+floattostr(pos.uv.y)+
                //') esta fora do triangulo v012('+inttostr(vertice[0].index)+','+inttostr(vertice[1].index)+','+inttostr(vertice[2].index)+')');
                //writeln(te,'v0123('+inttostr(vertice[0].index)+','+inttostr(vertice[1].index)+','+inttostr(vertice[2].index)+','+inttostr(vertice[3].index)+') Esta FORA do Quadrado!');

                pos.xy.x:=0;
                pos.xy.y:=0;
             end
         else
           begin
              //writeln(te,'v0123('+inttostr(vertice[0].index)+','+inttostr(vertice[1].index)+','+inttostr(vertice[2].index)+','+inttostr(vertice[3].index)+')');
              Converte_UV_XY_Beto(pos); //Poderia ser Converte_UV_XY soh
              pos.xy.Pixels(canvas,rgbtocolor(Trunc(vertice[0].index*50+300),Trunc(vertice[1].index*50+300),Trunc(vertice[2].index*50)));
           end;
//         write(te,'uv('+floattostr(pos.uv.x)+','+floattostr(pos.uv.y)+') xy('+floattostr(pos.xy.x)+','+floattostr(pos.xy.y)+')-');
//         flush(te);
         result:=pos.xy;

pos.xy.Destroy;
pos.uv.Destroy;
end;

procedure TImageCal.GravaMatrizCalibracao;
var i,j: integer;
begin

for i:=0 to NLinhas-1 do
 begin
   for j:=0 to NColunas-1 do
     begin
//     write(te,'('+floattostr(point_xy[i*NColunas+j].x)+','+floattostr(point_xy[i*NColunas+j].y)+')->'+
//       floattostr(point_uv[i*NColunas+j].x)+','+floattostr(point_uv[i*NColunas+j].y)+' # ');
     end;
   writeln(te);
 end;
flush(te);


end;

procedure TImageCal.GravaMatriz;
var
     i,j: integer;
     dist00,dist01: Double;   // Distancias do ponto para cada canto
     dist10,dist11: Double;
     x1,x2,y1,y2: integer; // Coordenadas em questao
     value_xy: xy;
     p: TMathPoint;
     disttotal: Double; // Distancia total
     prop00,prop01,prop10,prop11: Double; // Intensidade
     f: File of ShortInt;
     lines_x,lines_y: integer; // Apenas para performance
     lim, totaldist, mindist: Double; // Limite
     total_x,total_y: Double;
     media_x,media_y: Double;
     b: ShortInt;
     tamanhoArquivo: longint;
     ArquivoLogMessages: textfile;
begin


p:=TMathPoint.Create;
// showmessage('I');
     modo:=1;
     lim:=0.00001;
     
     lines_x:= resX div (NLinhas-1);
     lines_y:= resY div (NColunas-1);
//          // showmessage('HERE');
//     for i:=1 to NLinhas-1 do
//          for j:=1 to NColunas-1 do
//          begin
//               for x:=1 to
//               MaCal[i,j].x:=trunc((resX/(NLinhas-1))*(i));
//               MaCal[i,j].y:=trunc((resY/(NColunas-1))*(j));
//               MaCal[i,j].u:=0;
//               MaCal[i,j].v:=0;
//               MaCal[i,j].gravado:=false;
//          end;
// showmessage ('II');

     AssignFile(f,'/etc/brtablet/calib.new');
     AssignFile(ArquivoLogMessages,'debug3.txt');
     ReWrite(ArquivoLogMessages);
     ReWrite(f);
     Canvas.Clear;
// showmessage ('IIa');

     for x1:=0 to resX-1 do
     begin
         if (x1 div 100)=(x1/100) then
            begin
//             writeln(ArquivoLogMessages,'Processou Mensagem em x1='+inttostr(x1));
//             writeln(ArquivoLogMessages,'ContaArquivos'+inttostr(ContaArquivos));
//             flush(ArquivoLogMessages);
             Application.ProcessMessages;
             repaint;
             refresh;
             form1.Refresh;
             Application.ProcessMessages;
            end;


         for y1:=0 to resY-1 do
         begin
             //writeln(te,'x1 -> '+inttostr(x1)+'  y1 ->'+inttostr(y1));
             //flush(te);
             p.x:=x1;
             p.y:=y1;
             // showmessage ('IIc');

             p:=ProcessaCoordenada(p);

             value_xy.x:=Trunc(p.x);
             value_xy.y:=Trunc(p.y);
             b:=value_xy.x mod 256;
             Write(f,b);
             b:=value_xy.x div 256;
             Write(f,b);

             b:=value_xy.y mod 256;
             Write(f,b);
             b:=value_xy.y div 256;
             Write(f,b);

//             Write(f,value_xy);
         end;
     end;
//     CloseFile(f);

     // showmessage ('IIb');
//     p.destroy;
     Pinta;
     Form1.Refresh;
end;

procedure TImageCal.Grava;
begin
//       point_uv[ix*NColunas+iy].x:=trunc((xCursor/width)*resX);
//      point_uv[ix*NColunas+iy].y:=trunc((yCursor/height)*resY);
      point_uv[ix*NColunas+iy].x:=xCursor;
       point_uv[ix*NColunas+iy].y:=yCursor;
       gravado[ix*NColunas+iy]:=true;

end;

procedure TImageCal.Proximo;

begin
if ix<NLinhas-1 then ix:=ix+1 else
   begin
     ix:=0;
     if iy<NColunas-1 then iy:=iy+1
         else
           begin
               ix:=0;
               iy:=0;
           end;
   end;
   Pinta;
end;

Procedure TImageCal.MostraTriangulo;
var
  p: TMathPoint;
begin
  p:=TMathPoint.Create;
  p.x:=xCursor/ratiox;
  p.y:=yCursor/ratioy;
  ProcessaCoordenada(p);
  
  if vertice[0].index+vertice[1].index+vertice[2].index+vertice[3].index>0 then
  begin
   point_uv[vertice[0].index].Line(Canvas,vertice[1].xy);
   point_uv[vertice[1].index].Line(Canvas,vertice[2].xy);
   point_uv[vertice[2].index].Line(Canvas,vertice[3].xy);
   point_uv[vertice[3].index].Line(Canvas,vertice[0].xy);
  end;

  

//  vertice[1].xy.Line(Canvas,vertice[2].xy);
//  vertice[2].xy.Line(Canvas,vertice[0].xy);

  Canvas.Brush.Color:=clGreen;
  Canvas.Brush.Style:=bsSolid;
  vertice[0].xy.Ellipse(Canvas,4);
  Form1.Refresh;
  p.destroy;
end;

Procedure TImageCal.MouseMove(Shift: TShiftState; x,y:integer);
begin
  inherited MouseMove(Shift,x,y);

end;

procedure TImageCal.Load;
var i,j: integer;
begin
points_uv:=0;
points_xy:=0;
for i:=0 to NLinhas-1 do
   for j:=0 to NColunas-1 do
     begin
       point_xy[i*NColunas+j].x:=resX/(NLinhas-1)*i;
       point_xy[i*NColunas+j].y:=resY/(NColunas-1)*j;
//       MaCal[i,j].u:=0;
//       MaCal[i,j].v:=0;
//       MaCal[i,j].gravado:=false;
       point_uv[i*NColunas+j].x:=resX/(NLinhas-1)*i;
       point_uv[i*NColunas+j].y:=resY/(NColunas-1)*j;
       gravado[i*NColunas+j]:=true;
       points_xy:=points_xy+1;
       points_uv:=points_uv+1;
     end;
end;

constructor TImageCal.Create(AOwner: Tcomponent);
begin
   points_xy:= 0;
   points_uv:= 0;

   ix:=0;
   iy:=0;
   modo:=0;

  inherited Create(AOwner);
end;


procedure TImageCal.Pinta;

begin
   if modo=0 then
   begin
     ImageCal.Canvas.Brush.Color:=clWhite;
     ImageCal.Canvas.FillRect(0,0,imagecal.width,imagecal.height);
   end;
   ImageCal.Canvas.Brush.Color:=clBlack;

   if gravado[ix*NColunas+iy] then ImageCal.Canvas.Brush.Color:=clRed;

   Canvas.Brush.Color:=clBlack;
   Canvas.Brush.Style:=bsSolid;
   point_xy[ix*NColunas+iy].Ellipse(Canvas,DiaCir);

   MostraMatrizToques;

end;

procedure TImageCal.MostraPontoToque(p: TMathPoint);
var lx, ly: integer;
begin
  p.Cruz(canvas,15);
{  Canvas.Pen.Color:=clRed;
  Canvas.Pen.Width:=1;
  lx:=trunc((p.x/resX)*imagecal.width);
  ly:=trunc((p.y/resY)*imagecal.height);
//  lx:=trunc(p.x);
//  ly:=trunc(p.y);
  Canvas.Moveto(lx,ly-DiaCir);
  Canvas.LineTo(lx, ly+DiaCir);
  Canvas.MoveTo(lx-DiaCir,ly);
  Canvas.LineTo(lx+DiaCir,ly);}
end;

procedure TImageCal.MostraMatrizToques;
var i: integer;
begin
for i:=0 to points_xy do
  begin
    if gravado[i] then MostraPontoToque(point_uv[i]);
    Canvas.Brush.Color:=clyellow;
    Canvas.Brush.Style:=bsSolid;
    point_xy[i].Ellipse(Canvas,3);
  end;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
  );
begin
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: char);
begin

if key=char(32) then ImageCal.Proximo;
if key=char(13) then ImageCal.Grava;
if key=char(97) then ImageCal.GravaMatriz;
if key=char(98) then
  begin
    ImageCal.MostraTriangulo;
  end;
if key=char(99) then halt;
if key=char(100) then ImageCal.GravaMatrizCalibracao; // incluido no dia 07/05/2008


if key=char(113) then Application.Terminate;
//if key=char(114) then ImageCal.Reset;
//if key=char(115) then ImageCal.SalvaXY;

end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin

end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  a: integer;
//  data: devicetoken;
  data: array[0..6] of byte;
  charvalue: array [0..2] of byte;
begin
  a:=FpRead(ImageCal.DebugPipe,data,7);
  if(a<>7) then exit;

  // Posicao X
  for a:=0 to 6 do begin
    if (data[a]>=65) then begin
      data[a]:=data[a]-65+10;
    end else begin
      data[a]:=data[a]-48;
    end;
  end;
  ImageCal.xCursor:=(data[1]*256+data[2]*16+data[3]) div 2;
  ImageCal.yCursor:=(data[4]*256+data[5]*16+data[6]) div 2;

end;

procedure TForm1.Button1Click(Sender: TObject);
var i,j: integer;

begin

end;

procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
closefile(te);

end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: integer;

begin
  ContaArquivos:=0;
  AssignFile(te,'debug2.txt');
  //AssignFile(te2,'/home/victorpm/debug.txt');
  //reset(te2);
  //ShowMessage(inttostr(filesize(te2)));
  Rewrite(te);
  //writeln(te,'Arquivos:'+inttostr(ContaArquivos));
  //flush(te);

  ShowMessage(inttostr(screen.width)+','+inttostr(screen.height));

  Left:=0;
  Top:=0;
  Width := Screen.Width;
  Height := Screen.Height;
//  self.windowstate:=wsmaximized;

  ImageCal:=TImageCal.Create(Self);
  ImageCal.parent:=Form1;
  //ShowMessage(inttostr(self.width)+','+inttostr(self.height));
  ImageCal.DebugPipe:=FpOpen('/etc/brtablet/pipe',O_RDONLY or O_NONBLOCK);
  Timer1.Enabled:=True;

  //ImageCal.Stretch:=true;
  //ImageCal.Autosize:=true;

  ImageCal.top:=0;
  ImageCal.left:=0;
  //align:=alclient;
  ImageCal.Height:=screen.Height-1;
  ImageCal.Width:=screen.Width-1;

  ImageCal.Align:=alClient;
  ImageCal.Anchors:=[aktop,akleft,akright,akbottom];

  //ImageCal.EnableAutoSizing;

  ImageCal.Canvas.Brush.Color:=clWhite;
  ImageCal.Canvas.FillRect(0,0,imagecal.width,imagecal.height);


  ratiox:=imagecal.clientwidth/resX;
  ratioy:=imagecal.clientheight/resY;
  for i:=0 to 100 do
  begin
    ImageCal.point_xy[i]:=TMathPoint.Create;
    ImageCal.point_uv[i]:=TMathPoint.Create;
  end;
  for i:=0 to 4 do
  begin
    ImageCal.vertice[i].xy:=TMathPoint.Create;
  end;
  ImageCal.Load;
  ImageCal.Pinta;
end;

initialization
  {$I telapontos.lrs}

end.

